package api

import (
	"errors"
	// "bufio"
	"fmt"
	"io/ioutil"
	"net/http"
	"runtime/debug"

	"github.com/deploy-services/v2/KolonseWeb"
	"github.com/deploy-services/v2/KolonseWeb/HttpLib"
	"github.com/deploy-services/v2/KolonseWeb/Type"
	"github.com/deploy-services/v2/services"
)

func public_router(app *KolonseWeb.App) {
	// ?name=xxx
	app.Get("/api/public/history", public_history)
	// ?name=xxx
	app.Get("/api/public/show", public_show)
	// ?name=xxx
	app.Get("/api/public/commit", public_commit)
	// ?name=xxx&commit=xxx
	app.Get("/api/public/active", public_active)
}

func service_router(app *KolonseWeb.App) {
	// ?name=xxx
	app.Get("/api/service/history", service_history)
	// ?name=xxx
	app.Get("/api/service/show", service_show)
	// ?name=xxx
	app.Get("/api/service/commit", service_commit)
	// ?name=xxx&commit=xxx
	app.Get("/api/service/active", service_active)
	// ?name=xxx&node=xxx
	app.Get("/api/service/start", service_start)
	// ?name=xxx&node=xxx
	app.Get("/api/service/stop", service_stop)
	// ?name=xxx&node=xxx
	app.Get("/api/service/health", service_health)

	app.Post("/api/service/cmd", service_cmd)
}

func Load(app *KolonseWeb.App) {
	public_router(app)
	service_router(app)
	daemon_router(app)
	app.Get("/api/diff", diff)
	app.Get("/api/node/show", node_show)
	app.Get("/api/node/enable", node_enable)
	app.Post("/api/node/cmd", node_cmd)

	app.Get("/api/reload", reload)
	app.Get("/api/use", use)
	app.Get("/api/package/commit", pack_commit)
	app.Get("/api/sync", sync)
	app.Post("/api/service/push", service_push_file)
	app.Post("/api/package/push", package_push_file)
}

func parse_file(req *HttpLib.Request, res *HttpLib.Response, next Type.Next) (string, []byte, error) {
	contentType := req.Header.Get("Content-Type")
	if contentType[:19] != "multipart/form-data" {
		res.WriteHeader(http.StatusUnsupportedMediaType)
		return "", nil, errors.New("不支持的 Content-Type")
	}
	err := req.ParseMultipartForm(10 << 20)
	if err != nil {
		res.WriteHeader(http.StatusBadRequest)
		return "", nil, err
	}

	file, header, err := req.FormFile("file")
	if err != nil {
		res.WriteHeader(http.StatusBadRequest)
		return "", nil, err
	}
	defer file.Close()

	filename := header.Filename
	content, err := ioutil.ReadAll(file)
	if err != nil {
		http.Error(res, "获取文件失败: "+err.Error(), http.StatusBadRequest)
		return "", nil, err
	}

	return filename, content, nil
}

func service_push_file(req *HttpLib.Request, res *HttpLib.Response, next Type.Next) {
	filename, content, err := parse_file(req, res, next)
	if err != nil {
		res.Write([]byte(err.Error()))
		return
	}
	defer func() {
		if r := recover(); r != nil {
			res.Write([]byte(fmt.Sprintln(r)))
			res.Write(debug.Stack())
		}
	}()

	name := req.FormValue("name")
	node := req.FormValue("node")
	resp := services.ServicePush(name, node, filename, content)
	res.Write([]byte(resp))
}

func package_push_file(req *HttpLib.Request, res *HttpLib.Response, next Type.Next) {
	filename, content, err := parse_file(req, res, next)
	if err != nil {
		res.Write([]byte(err.Error()))
		return
	}
	defer func() {
		if r := recover(); r != nil {
			res.Write([]byte(fmt.Sprintln(r)))
			res.Write(debug.Stack())
		}
	}()

	resp := services.PackagePush(filename, content)
	res.Write([]byte(resp))
}

func pack_commit(req *HttpLib.Request, res *HttpLib.Response, next Type.Next) {
	defer func() {
		if r := recover(); r != nil {
			res.Write([]byte(fmt.Sprintln(r)))
			res.Write(debug.Stack())
		}
	}()
	resp := services.PackageCommit()
	res.Write([]byte(resp))
}

func diff(req *HttpLib.Request, res *HttpLib.Response, next Type.Next) {
	defer func() {
		if r := recover(); r != nil {
			res.Write([]byte(fmt.Sprintln(r)))
			res.Write(debug.Stack())
		}
	}()
	resp := services.ShowDiff()
	res.Write([]byte(resp))
}

// 重新加载配置
func reload(req *HttpLib.Request, res *HttpLib.Response, next Type.Next) {
	defer func() {
		if r := recover(); r != nil {
			res.Write([]byte(fmt.Sprintln(r)))
			res.Write(debug.Stack())
		}
	}()
	services.Reload()
	res.Write([]byte("Completed"))
}

// 重新加载配置
func use(req *HttpLib.Request, res *HttpLib.Response, next Type.Next) {
	defer func() {
		if r := recover(); r != nil {
			res.Write([]byte(fmt.Sprintln(r)))
			res.Write(debug.Stack())
		}
	}()

	file := req.URL.Query().Get("file")
	services.Use(file)
	res.Write([]byte("Completed"))
}

func sync(req *HttpLib.Request, res *HttpLib.Response, next Type.Next) {
	defer func() {
		if r := recover(); r != nil {
			res.Write([]byte(fmt.Sprintln(r)))
			res.Write(debug.Stack())
		}
	}()

	// file := req.URL.Query().Get("file")
	resp := services.Sync()
	res.Write([]byte(resp))
}
